package com.shtb.wisdom.videotaker

import android.annotation.TargetApi
import android.app.Activity
import android.hardware.Camera
import android.media.CamcorderProfile
import android.media.MediaPlayer
import android.media.MediaRecorder
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.util.DisplayMetrics
import android.util.Log
import android.view.*
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Response
import java.io.File
import java.io.IOException
import java.util.*

class VideoTakerActivity: BaseActivity(), MediaRecorder.OnErrorListener, SurfaceVideoView.OnPlayStateListener, MediaPlayer.OnPreparedListener,
    MediaPlayer.OnCompletionListener, MediaPlayer.OnInfoListener,
    MediaPlayer.OnErrorListener {
    // 导出小视频宽度
    var Small_Video_Width = 640
    // 导出小视频高度
    var Small_Video_Height = 480

    // 录制音视频的句柄
    private var mMediaRecorder: MediaRecorder? = null
    // 相机
    private var mCamera: Camera? = null
    // 预览录制视图
    lateinit var mMediaView: SurfaceView
    // 控制 SurfaceView 显示的句柄
    lateinit var mSurfaceHolder: SurfaceHolder
    // 播放视图
    lateinit var mVideoView: SurfaceVideoView
    // 视频录制按钮
    lateinit var recordButton: RecordButton
    // 返回按钮
    lateinit var closeButton: Button
    // 完成按钮
    lateinit var finishButton: TextView
    // 是否正在录制
    private var isRecording = false
    // 防止结束按钮🔘重复被点击
    private var guardRepeatClick = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 防止锁屏
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        setContentView(R.layout.activity_videotaker)
        // 录制最大时间
        mRecordMaxTime = intent.getIntExtra("recordMaxTime", 300)
        // 预览录制视图
        mMediaView = findViewById(R.id.video_surfaceview)
        // 录制句柄
        mSurfaceHolder = mMediaView.holder
        mSurfaceHolder.addCallback(CustomCallBack())
        //在 Camera图像预览中就使用该类型的 Surface，由 Camera负责提供给预览 Surface数据
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)

        // 播放视图
        mVideoView = findViewById(R.id.video_player)
        finishButton = findViewById(R.id.video_finish)
        recordButton = findViewById(R.id.video_button)
        closeButton = findViewById(R.id.video_close)
        closeButton.setOnClickListener {
            deinitMediaRecorder()
            deinitCamera()
            if (mRecordFile?.exists() == true) {
                deleteSingleFile(mRecordFile!!.absolutePath)
            }
            intent.putExtra("videoTaker", "\"{\"status\":\"error\",\"msg\":\"用户已取消\"}\"")
            setResult(Activity.RESULT_CANCELED, intent)
            finish()
        }
        recordButton.setOnClickListener {
            if (!isRecording) {
                //显示录制⏺️预览
                mMediaView.visibility = View.VISIBLE
                //隐藏播放视图
                mVideoView.visibility = View.GONE
                finishButton.visibility = View.GONE
                //删除当前录制等视频
                if (mRecordFile?.exists() == true) {
                    deleteSingleFile(mRecordFile!!.absolutePath)
                }
                it.setBackgroundResource(R.drawable.btn_video_shooting)
                record()
                isRecording = true
            } else {
                if (guardRepeatClick) {//结束录制之前，先不允许用户重复点击，防闪退

                } else {
                    guardRepeatClick = true
                    finishRecording()
                }
            }
        }
        finishButton.setOnClickListener {
            upload()
        }
        val metrics = getScreenMetrics(this)
        val videoHight = metrics.heightPixels
        mVideoView!!.layoutParams.height = videoHight
        mVideoView!!.requestLayout()
        mVideoView!!.setOnPreparedListener(this)
        mVideoView!!.setOnPlayStateListener(this)
        mVideoView!!.setOnErrorListener(this)
        mVideoView!!.setOnClickListener {

        }
        mVideoView!!.setOnInfoListener(this)
        mVideoView!!.setOnCompletionListener(this)
    }

    private fun getScreenMetrics(context: Activity): DisplayMetrics {
        val mDisplayMetrics = DisplayMetrics()
        context.windowManager.defaultDisplay.getMetrics(mDisplayMetrics)
        return mDisplayMetrics
    }

    private var mTimer: Timer? = null
    private var mTimerTask: TimerTask? = null

    // 一次拍摄默认时长 15 秒
    var mRecordMaxTime: Int = 300
    // 当前计数时间
    var timeCount: Int = 0
    // 文件
    private var mRecordFile: File? = null

    /**
     * SurfaceView的生命周期管理
     */
    private inner class CustomCallBack : SurfaceHolder.Callback {
        override fun surfaceCreated(holder: SurfaceHolder?) {
            initCamera()
        }

        override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {

        }

        override fun surfaceDestroyed(holder: SurfaceHolder) {
            deinitCamera()
        }
    }

    /**
     * 开始录制视频
     * @param onRecordFinishListener
     * 达到指定时间之后回调接口
     */
    fun record() {
        createRecordDir()
        try {
            if (mCamera == null) {
                initCamera()
            }
            initRecord()
            timeCount = 0 // 时间计数器重新赋值
            mTimer = Timer()
            mTimerTask = object : TimerTask() {
                override fun run() {
                    mHandler.sendEmptyMessage(1)
                }
            }
            mTimer!!.schedule(mTimerTask, 0, 50)
            guardRepeatClick = false
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    private fun upload() {
        if (mRecordFile?.exists() == true) {
            showLoading("正在上传")
            VideoTakerService().recordVideoUpload(mRecordFile!!.absolutePath, object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    hideLoading()
                    Log.i("video", e.message)
                    Toast.makeText(this@VideoTakerActivity, e.message, Toast.LENGTH_SHORT).show()
                }

                @Throws(IOException::class)
                override fun onResponse(call: Call, response: Response) {
                    hideLoading()
                    var responseString = response.message
                    if (response.isSuccessful) {
                        responseString = response.body!!.string()
                    }
                    intent.putExtra("videoRecord", responseString)
                    setResult(RESULT_OK, intent)
                    finish()
                }
            })
        }
    }

    // 初始化相机
    private fun initCamera() {
        if (mCamera != null) {
            deinitCamera()
        }
        try {
            mCamera = Camera.open()
        } catch (e: Exception) {
            e.printStackTrace()
            deinitCamera()
        }
        if (mCamera != null) {
            mCamera!!.lock()
            val params = mCamera!!.parameters
            //设置摄像头为竖屏
            params["orientation"] = "portrait"
            val previews =
                params.supportedPreviewSizes
            val videosizes =
                params.supportedVideoSizes
            val preWidth = previews[0].width
            params.setPreviewSize(preWidth, previews[0].height)
            val videoSize = bestVideoSize(preWidth, videosizes)
            Small_Video_Width = videoSize.width
            Small_Video_Height = videoSize.height
            //设置摄像头自动对焦
            params.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO
            mCamera!!.parameters = params
            //camera 摄像头默认的角度是横屏，所以预设拍摄角度偏转 90度
            mCamera!!.setDisplayOrientation(90)
            mCamera!!.setPreviewDisplay(mSurfaceHolder)
            mCamera!!.startPreview()
            mCamera!!.unlock()
        }
    }

    private fun initRecord() {
        if (mMediaRecorder != null) {
            mMediaRecorder!!.reset()
        } else {
            mMediaRecorder = MediaRecorder()
            mMediaRecorder!!.setOnErrorListener(this)
        }
        try {
            if (mCamera != null) mMediaRecorder!!.setCamera(mCamera)
            mMediaRecorder!!.setPreviewDisplay(mSurfaceHolder.surface)
            //设置视频数据源
            mMediaRecorder!!.setVideoSource(MediaRecorder.VideoSource.CAMERA)
            //设置音频数据源
            mMediaRecorder!!.setAudioSource(MediaRecorder.AudioSource.DEFAULT)
            //设置视频输出的编码格式
            mMediaRecorder!!.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
            //设置音频输出的编码格式
            mMediaRecorder!!.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
            //设置所录制视频的编码格式
            mMediaRecorder!!.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
            //设置所录制视频的编码位率
            val mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH_SPEED_720P)
            if (mProfile.videoBitRate > 2 * 1024 * 1024) mMediaRecorder!!.setVideoEncodingBitRate(2 * 1024 * 1024) else mMediaRecorder!!.setVideoEncodingBitRate(
                mProfile.videoBitRate
            )
            //设置所录制的声音的编码位率
            mMediaRecorder!!.setAudioEncodingBitRate(44100)
            //输出旋转90度，保持竖屏录制
            mMediaRecorder!!.setOrientationHint(90)
            //设置要拍摄的宽度和视频的高度
            mMediaRecorder!!.setVideoSize(Small_Video_Width, Small_Video_Height)
            //设置录制的文件的保存位置
            mMediaRecorder!!.setOutputFile(mRecordFile!!.absolutePath)
            //准备录制
            mMediaRecorder!!.prepare()
            //开始录制
            mMediaRecorder!!.start()
        } catch (e: RuntimeException) {
            e.printStackTrace()
            Log.i("video_taker", e.message ?: "")
        }
    }

    // 销毁 mCamera
    private fun deinitCamera() {
        mCamera?.let {
            it.setPreviewCallback(null)//这个在前面，否则退出出错
            it.stopPreview()
            it.release()
        }
        mCamera = null
    }

    private fun stopMediaRecorder() {
        try {
            mMediaRecorder?.stop()
        } catch (e: RuntimeException) {

        }
        mMediaRecorder?.reset()
    }

    // 销毁 mMediaRecorder
    private fun deinitMediaRecorder() {
        try {
            mMediaRecorder?.stop()
        } catch (e: RuntimeException) { // 此处不用 stop方法抛出的 IllegalStateException，而用父级，捕获 MediaRecorder其他异常
            Log.i("video_taker", e.message ?: "")
        }
        mMediaRecorder?.reset()
        mMediaRecorder?.release()
        mMediaRecorder = null
    }
    
    // 恢复录制按钮🔘状态
    private fun normalStatement() {
        recordButton.setProgress(0f)
        recordButton.setBackgroundResource(R.drawable.btn_video_shoot)
        if (mTimer != null) {
            mTimer?.cancel()
            mTimer = null
        }
    }

    //录制完成回调
    private fun finishRecording() {

        // 恢复录制按钮🔘状态
        normalStatement()
        // 停止录制
        stopMediaRecorder()

        mVideoView!!.setVideoPath(mRecordFile!!.absolutePath)
        mVideoView.visibility = View.VISIBLE
        finishButton.visibility = View.VISIBLE
        mMediaView.visibility = View.GONE
        // 录制结束状态
        isRecording = false
    }

    private var mNeedResume = false
    override fun onResume() {
        super.onResume()
        if (mVideoView != null && mNeedResume) {
            mNeedResume = false
            if (mVideoView!!.isRelease) mVideoView!!.reOpen() else mVideoView!!.start()
        }
    }

    override fun onPause() {
        super.onPause()
        if (mVideoView != null) {
            if (mVideoView!!.isPlaying) {
                mNeedResume = true
                mVideoView!!.pause()
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        deinitMediaRecorder()
        deinitCamera()
    }
    
    private val mHandler: Handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            timeCount += 1
            val rate = timeCount.toFloat() / mRecordMaxTime.toFloat()
            recordButton.setProgress(rate)
            if (timeCount > mRecordMaxTime) {
                // 结束录制
                finishRecording()
            }
        }
    }

    override fun onError(mr: MediaRecorder?, what: Int, extra: Int) {
        try {
            mr?.reset()
        } catch (e: IllegalStateException) {
            e.printStackTrace()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    override fun onPrepared(mp: MediaPlayer) {
        mVideoView!!.setVolume(SurfaceVideoView.getSystemVolumn(this))
        mVideoView!!.start()
    }

    override fun dispatchKeyEvent(event: KeyEvent): Boolean {
        when (event.keyCode) {
            KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP -> mVideoView!!.dispatchKeyEvent(
                this,
                event
            )
        }
        return super.dispatchKeyEvent(event)
    }

    override fun onStateChanged(isPlaying: Boolean) {}
    override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean {
        try {
            mp.reset()
        } catch (e: IllegalStateException) {
            e.printStackTrace()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        if (!isFinishing) {
            // 播放失败
        }
        finish()
        return false
    }

    override fun onCompletion(mp: MediaPlayer) {
        if (!isFinishing) mVideoView!!.reOpen()
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    override fun onInfo(mp: MediaPlayer, what: Int, extra: Int): Boolean {
        when (what) {
            MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING -> {
            }
            MediaPlayer.MEDIA_INFO_BUFFERING_START -> if (!isFinishing) mVideoView!!.pause()
            MediaPlayer.MEDIA_INFO_BUFFERING_END -> if (!isFinishing) mVideoView!!.start()
            MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START -> mVideoView!!.background = null
        }
        return false
    }

    // 创建文件路径
    private fun createRecordDir() {
        val sampleDir =
            File(filesDir.toString() + "/Media_Video")
        if (!sampleDir.exists()) {
            sampleDir.mkdirs()
        }
        // 创建文件
        try {
            mRecordFile = File.createTempFile("recordVideo", ".mp4", sampleDir) //mp4格式
            val mFilePath = mRecordFile?.getAbsolutePath()
            Log.i("path", mFilePath)
        } catch (e: IOException) {
            Log.i("file", e.toString())

        }
    }

    companion object {

        fun delete(delFile: String?): Boolean {
            val file = File(delFile)
            return if (!file.exists()) {
                Log.e("--Method--", "删除文件失败:" + delFile + "不存在！")
                false
            } else {
                deleteSingleFile(delFile)
            }
        }

        /** 删除单个文件
         * @param filePathName 要删除的文件的文件名
         * @return 单个文件删除成功返回true，否则返回false
         */
        fun deleteSingleFile(`filePath$Name`: String?): Boolean {
            val file = File(`filePath$Name`)
            // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
            return if (file.exists() && file.isFile) {
                if (file.delete()) {
                    Log.e(
                        "--Method--",
                        "Copy_Delete.deleteSingleFile: 删除单个文件" + `filePath$Name` + "成功！"
                    )
                    true
                } else {
                    Log.e("--Method--", "删除单个文件" + `filePath$Name` + "失败！")
                    false
                }
            } else {
                Log.e("--Method--", "删除单个文件失败：" + `filePath$Name` + "不存在！")
                false
            }
        }
    }

    private fun bestVideoSize(
        _w: Int,
        videoSizes: List<Camera.Size>
    ): Camera.Size {
        //降序排列
        Collections.sort(
            videoSizes
        ) { lhs, rhs ->
            if (lhs.width > rhs.width) {
                -1
            } else if (lhs.width == rhs.width) {
                0
            } else {
                1
            }
        }
        for (i in videoSizes.indices) {
            if (videoSizes[i].width < _w / 2) {
                return videoSizes[i]
            }
        }
        return videoSizes[0]
    }
}